home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 101_01 / yahtzee.c < prev    next >
Text File  |  1985-11-13  |  12KB  |  385 lines

  1. /* YAHTZEE Dice game            Steve Ward
  2.  * USAGE:
  3.  *
  4.  *    yahtzee [-dn] name1 name2 name3 ...
  5.  * where the namei are player's names, prefixed by = for automated
  6.  * (computer) players.
  7.  *
  8.  *    yahtzee
  9.  * for solitaire.
  10.  *
  11.  * USE special function keys to select dice, roll selected dice, and end
  12.  *  an inning; keypad up/down arrows select where to enter your score.
  13.  *
  14.  * See YAHTZEE.HLP for full instructions.
  15.  *
  16.  * COMPILE and CLINK with CIO.CRL!
  17.  */
  18.  
  19. #define    ROLLX    39        /* Coordinates for light buttons.    */
  20. #define    DONEX    46
  21. #define    PASSX    53
  22. #define    OOPSX    60
  23. #define    OOPSC    'R'
  24. #define    PASSC    'Q'
  25. #define    DONEC    'P'
  26. #define    ROLLC    'J'
  27.  
  28. #define    GOX    45        /* Coordinates for prompt.        */
  29. #define    GOY    22
  30. #define    GAMEY    20
  31.  
  32. #define    SCOREX    30        /* leftmost column for scores        */
  33. #define    DIEY    22
  34. #define    LABLIN    24        /* Line for labels            */
  35. #define    PLAYERS    10        /* Max number of players        */
  36. #define    NONE    127        /* char-size illegal value.        */
  37.  
  38. char Dice[5];
  39. char nplayers;            /* actual number of players.        */
  40. char Potent[13];        /* Potential score...            */
  41. char PotKind, PotSum, PotStr;    /* Filled by Pot            */
  42. char PotMax, PotCnt;
  43.  
  44. struct Player
  45.  { char Scores[13];        /* Scores, or 127 iff none yet.        */
  46.    char Select;            /* Currently selected category.        */
  47.    char Col;            /* Column number, for scores.        */
  48.    char Name[40];        /* Name of player.            */
  49.    int  Total;            /* total score.                */
  50.    int  Games;
  51.  } Who[PLAYERS];
  52.  
  53. /* Initialize a player:                            */
  54.  
  55. iplayer(name, pl)
  56.  char *name;    struct Player *pl;
  57.  {    char i, *fake;    fake = "==0==";
  58.     if ((!name[1]) && (*name == '=')) { name = fake; name[3]++; }
  59.     for (i=0; i<13; i++) pl->Scores[i] = NONE;
  60.     pl->Select = NONE;
  61.     for (i=0; pl->Name[i] = name[i]; i++); }
  62.  
  63. Buzz() { putchar(7); }
  64. MoveTo(x, y) { puts("\033Y"); putchar(y+32); putchar(x+32); }
  65.  
  66. char ShowX, ShowY, *ShowSc; int ShowTot;
  67.  
  68. Show1(n, flag)
  69.  char n, flag;
  70.  {    int val;
  71.     MoveTo(ShowX, ShowY++);
  72.     if (n == 255) val = ShowTot;    else val = ShowSc[n];
  73.     if (!flag) { puts("\033p");    val = Potent[n]; }
  74.     else if (flag == 44) puts("\033p");
  75.     if (val == NONE) puts("  ? ");
  76.     else { printf(" %2d", val); ShowTot += val; }
  77.     if (!flag || (flag == 44)) puts("\033q"); }
  78.  
  79. Show(pl)        /* Show the scores of a player.        */
  80.  char pl;
  81.  {    struct Player *p;    char cc, tot, f, j;
  82.     Pot(pl);
  83.     ShowX = (p = &Who[pl])->Col-1;    ShowY = 1;    ShowTot = 0;
  84.     ShowSc = p->Scores;    cc = 0;        f = p->Select;
  85.     Show1(cc++,f--);    Show1(cc++,f--);    Show1(cc++,f--);
  86.     Show1(cc++,f--);    Show1(cc++,f--);    Show1(cc++,f--);
  87.     tot = ShowTot;    Show1(255,44);    ShowTot = j = tot>=63? 35:0;
  88.     Show1(255,44);
  89.     tot = ShowTot = tot+j;    Show1(255,44);    ShowTot = tot;
  90.     ShowY++;
  91.     Show1(cc++,f--);    Show1(cc++,f--);    Show1(cc++,f--);
  92.     Show1(cc++,f--);    Show1(cc++,f--);    Show1(cc++,f--);
  93.     Show1(cc++,f--);
  94.     p->Total = ShowTot;
  95.     Show1(255,44); }
  96.  
  97. char Straight(die)    /* Gives longest straight starting at die    */
  98.  {    char i, j;
  99.     for (i=1; i<6; i++)
  100.      { die++;
  101.        for (j=0; j<5; j++) if (Dice[j] == die) goto hit;
  102.        break;
  103.    hit:       continue; }
  104.     return i; }
  105.  
  106. char Kind(die)        /* Gives number of dice of count die        */
  107.  {    char count, i;
  108.     for (i=count=0; i<5; i++) if (die == Dice[i]) count++;
  109.     return count; }
  110.  
  111. Pot(pl)        /* Compute potential scores for player.        */
  112.  char pl;
  113.  {    char i,j,k;
  114.     for (i=0; i<13; i++) Potent[i] = 0;
  115.     for (i=0; i<5; i++) if (((j = Dice[i])>0) && (j<7)) Potent[j-1] += j;
  116.     for (PotMax=PotSum=i=PotKind=0; i<5; i++)
  117.      { PotKind |= (1<<(j=Kind(k=Dice[i]))); PotSum += Dice[i];
  118.        if (j>PotMax) { PotMax=j; PotCnt=k; }}
  119.     Potent[12] = PotSum;
  120.     if ((PotKind & 0xC) == 0xC) Potent[8] = 25;
  121.     if (PotKind & 0x38) Potent[6] = PotSum;
  122.     if (PotKind & 0x30) Potent[7] = PotSum;
  123.     if (PotKind & 0x20) Potent[11] = 50;
  124.     for (i=PotStr=0; i<5; i++) if ((j = Straight(Dice[i])) > PotStr)
  125.         PotStr=j;
  126.     if (PotStr >= 4) Potent[9] = 30;
  127.     if (PotStr == 5) Potent[10] = 40; }
  128.  
  129.  
  130. Play(pl)        /* Make a player's move; returns 0 iff OK. */
  131.  char pl;
  132.  {    Pot(pl);
  133.     Who[pl].Scores[Who[pl].Select] = Potent[Who[pl].Select]; }
  134.  
  135. Bd(f)
  136.  char f;
  137.  {    char i, *cc;
  138.     cc = " . ";
  139.     if (f == 1) { puts("\033F"); cc = "iii"; }
  140.     else if (!f) puts("\033q");
  141.     for (i=((80-SCOREX)/3); i--;) puts(cc);
  142.     puts("\033p\033G\n"); }
  143.  
  144. Board()
  145.  {    char i;
  146.     printf("\033H\033J\033p\033G");
  147.     printf(" H89 YAHTZEE 1.1            \033F");
  148.     for (i=48; i--;) putchar('i'); puts("\033G\n");
  149.     printf("        ACES        ADD 1's "); Bd(0);    /* Y = 1 */
  150.     printf("        TWOS        ADD 2's "); Bd(0);
  151.     printf("        THREES      ADD 3's "); Bd(0);
  152.     printf("        FOURS       ADD 4's "); Bd(0);
  153.     printf("        FIVES       ADD 5's "); Bd(0);
  154.     printf("        SIXES       ADD 6's "); Bd(0);
  155.     printf("   Subtotal  .  .  .  .  .  "); Bd(2);        /* Y = 7 */
  156.     printf("   Bonus iff >= 63       35 ");    Bd(2);        /* Y = 8 */
  157.     printf("TOTAL ABOVE   .  .  .  .  . ");    Bd(2);        /* Y = 9 */
  158.     printf("                            \n");
  159.            printf("        3 of a kind     SUM ");    Bd(0);    /* Y = 11 */
  160.     printf("        4 of a kind     SUM ");    Bd(0);
  161.     printf("        Full House       25 ");    Bd(0);
  162.     printf("        4 Straight       30 ");    Bd(0);
  163.     printf("        5 Straight       40 ");    Bd(0);
  164.     printf("        YAHTZEE          50 ");    Bd(0);
  165.     printf("        Chance          SUM ");    Bd(0);
  166.     printf("TOTAL SCORE   .  .  .  .  . ");    Bd(2);
  167.     MoveTo(0, GAMEY);
  168.     printf("GAMES   .  .  .  .  .  .  . "); Bd(1);
  169.     puts("\033p\033F");
  170.     MoveTo(ROLLX, LABLIN);    puts("i ROLL i");
  171.     MoveTo(DONEX, LABLIN);    puts("i DONE i");
  172.     MoveTo(PASSX, LABLIN);    puts("i      i");
  173.     MoveTo(OOPSX, LABLIN);    puts("i OOPS i");
  174.     puts("\033q\033G");
  175.  }
  176.  
  177. #define    TOP    0
  178. #define    MID    8
  179. #define    BOT    16
  180. Die(number, count)
  181.  {    char i, j;
  182.     if (count) puts("\033p\033F");
  183.     for (i=0; i<3; i++)
  184.      { MoveTo(4+(7*number), DIEY+i);
  185.        switch (count+(i<<3))
  186.         {    case TOP: case MID: case BOT:
  187.             case TOP+1: case BOT+1:
  188.             case MID+2:
  189.             case MID+4:    puts("     "); break;
  190.             case TOP+2:
  191.             case TOP+3:    puts("^    "); break;
  192.             case MID+1:
  193.             case MID+3:
  194.             case MID+5:    puts("  ^  "); break;
  195.             case BOT+2:
  196.             case BOT+3:    puts("    ^"); break;
  197.             case TOP+4:    case BOT+4:
  198.             case TOP+5:    case BOT+5:
  199.             case TOP+6:    case MID+6:    case BOT+6:
  200.                     puts("^   ^"); break; }}
  201.     Dice[number] = count;
  202.     puts("\033G\033q"); }
  203.  
  204.  
  205. Roll()
  206.  {    char i;
  207.     for (i=0; i<5; i++) if (!Dice[i]) Die(i, 1+rand()%6); } int    DTime;
  208.  
  209. Go(rolls, player)
  210.  char rolls, player;
  211.  {    char ch, i, save[5];
  212.     Pot(player);
  213.     for (i=0; i<5; i++) Dice[i] = 0;    Roll();
  214.     Who[player].Select = 12;
  215.     if (!Cycle(player, 1)) return 0;
  216.  
  217. Top:    for (i=0; i<5; i++) save[i] = Dice[i];
  218. nsc:    Show(player);
  219.     for (;;)
  220.     { MoveTo(GOX, GOY);
  221.       printf("\033q\033G%s's move: %d rolls left. \033K",
  222.         Who[player].Name, rolls);
  223. esc:      if (Who[player].Name[0] == '=') ch = Auto(player, rolls);
  224.       else ch = getchar();
  225.       switch (ch)
  226.       { case 033:    goto esc;
  227.         case '8':    Cycle(player, -1);    Show(player);    continue;
  228.         case ' ':
  229.         case '2':    Cycle(player, 1);    Show(player);    continue;
  230.         case 'S': case 'T': case 'U': case 'V': case 'W':
  231.              if (!rolls) Buzz();
  232.             else Die(ch - 'S', 0); continue;
  233.         case 0177:
  234.         case OOPSC:    for (i=0; i<5; i++) Die(i, save[i]); continue;
  235.         case ROLLC:    if (rolls>0) { Roll(); rolls--; }
  236.             else Buzz(); goto Top;
  237.         case DONEC:
  238.         case '\r':
  239.         case PASSC:    Play(player);
  240.             Who[player].Select = NONE;    Show(player);
  241.                 return ch;
  242.         default:    putchar(7); continue; }}}
  243.  
  244. /* Make move for a computer player:                */
  245.  
  246. int AutoPar[10];    /* Heuristic parameters -HA#, -HB#, etc.    */
  247.  
  248. char Auto(pl, rolls)
  249.  char pl, rolls;
  250.  {    char gofor, choice, i, j, *sc;
  251.     int value[13], target[6], best, n;
  252.     sc = Who[pl].Scores;
  253.     Pot(pl);
  254.     MoveTo(GOX, GOY+1); printf("Hmmm ... lemme think.\033K",
  255.         value[choice]);
  256.     Delay(DTime);
  257.  
  258.     for (i=0; i<13; i++)
  259.      { if (sc[i] != NONE) value[i] = i-99;
  260.        else    if (i<6) value[i] = 2*(Potent[i]-3*(i+1));/* face counts */
  261.        else if (i==6) value[i] = Potent[i]-20;    /* 3 of a kind */
  262.        else if (i==7) value[i] = Potent[i]-15;    /* 4 of a kind */
  263.        else if (i==9) value[i] = Potent[i]-12;    /* 4 straight  */
  264.        else if (i==10) value[i] = P